#include "play_voice.h"
#include "includes.h"

#include "audio_example_file.h"
#include "asr.h"
#include "user_spi.h"
#include "PANEL_sdk.h"

#define debug_voice_data 0 //是否输出音频插值后的信息

//desire_sample为目标采样率，original_sample为原始采样率，desire_sample要为original_sample的整数倍
#define original_sample 16000
#define desire_sample 48000

void play_voice(const unsigned char voice[], int tot_size)
{

	int16_t now, next, new;

	gpio_set_level(21, 1);
	ESP_LOGI(TAG, "Playing file example: \n");
	int offset = 0;

	ESP_LOGI(TAG, "tot_size: %d\n", tot_size);

	int8_t *resample_buff = (int8_t *)calloc(18 * 1024, sizeof(char));

	int8_t *i2s_write_buff = (int8_t *)calloc(18 * 1024, sizeof(char));
	size_t bytes_written;
	vTaskDelay(pdMS_TO_TICKS(60));

	ESP_LOGI(TAG, "start play\n");

	while (offset < tot_size)
	{ //播放结束

		int play_len = ((tot_size - offset) > (2 * 1024)) ? (2 * 1024) : (tot_size - offset); //每次播放2048

		uint32_t j = 0;
		for (int i = 0; i < play_len; i = i + 2)
		{

			now = (((uint8_t *)voice + offset)[i + 1] << 8) + ((uint8_t *)voice + offset)[i];
			next = (((uint8_t *)voice + offset)[i + 3] << 8) + ((uint8_t *)voice + offset)[i + 2];

			for (int idx = 0; idx < (int)desire_sample / original_sample; idx++)
			{
				new = (int16_t)((float)now * (1.0f - (original_sample / desire_sample) * idx) + (float)next * (original_sample / desire_sample) * idx);
				resample_buff[j++] = new & 0x00ff;
				resample_buff[j++] = new >> 8;
			}
		}

		uint32_t k = 0;
		for (int i = 0; i < j; i++)
		{
			i2s_write_buff[k++] = resample_buff[i++];
			i2s_write_buff[k++] = resample_buff[i];
			i2s_write_buff[k++] = resample_buff[i - 1];
			i2s_write_buff[k++] = resample_buff[i];
		}

		int i2s_wr_len = k;

		i2s_write(I2S_NUM_0, i2s_write_buff, i2s_wr_len, &bytes_written, portMAX_DELAY);
		offset += play_len; //累计播放数量自加
#if debug_voice_data
		printf("i2s_wr_len : %d j:  %d\n", i2s_wr_len, j);
		printf("======\n");
		for (int i = 0; i < 48; i += 2)
		{
			printf("%04x ", ((i2s_write_buff[i + 1] << 8) + i2s_write_buff[i]));
			if ((i + 1) % 15 == 0)
			{
				printf("\n");
			}
		}
		printf("======\n");
#endif
	}

	free(resample_buff);
	free(i2s_write_buff);
	gpio_set_level(21, 0);
	ESP_LOGI(TAG, "stop pa mute,free music cache");
}

void play_spi_voice(char *voice, int tot_size)
{

	int16_t now, next, new;

	gpio_set_level(21, 1);
	ESP_LOGI(TAG, "Playing spi in: \n");
	int offset = 0;

	ESP_LOGI(TAG, "tot_size: %d\n", tot_size);

	int8_t *resample_buff = (int8_t *)calloc(8 * 1024, sizeof(char));

	int8_t *i2s_write_buff = (int8_t *)calloc(16 * 1024, sizeof(char));
	size_t bytes_written;

	vTaskDelay(pdMS_TO_TICKS(10));
	ESP_LOGI(TAG, "start play\n");

	while (offset < tot_size)
	{ //播放结束

		int play_len = ((tot_size - offset) > (2 * 1024)) ? (2 * 1024) : (tot_size - offset); //每次播放2048

		uint32_t j = 0;
		for (int i = 0; i < play_len; i = i + 2)
		{

			now = (((uint8_t *)voice + offset)[i + 1] << 8) + ((uint8_t *)voice + offset)[i];
			next = (((uint8_t *)voice + offset)[i + 3] << 8) + ((uint8_t *)voice + offset)[i + 2];

			for (int idx = 0; idx < (int)desire_sample / original_sample; idx++)
			{
				new = (int16_t)((float)now * (1.0f - (original_sample / desire_sample) * idx) + (float)next * (original_sample / desire_sample) * idx);
				resample_buff[j++] = new & 0x00ff;
				resample_buff[j++] = new >> 8;
			}
		}

		uint32_t k = 0;
		for (int i = 0; i < j; i++)
		{
			i2s_write_buff[k++] = resample_buff[i++];
			i2s_write_buff[k++] = resample_buff[i];
			i2s_write_buff[k++] = resample_buff[i - 1];
			i2s_write_buff[k++] = resample_buff[i];
		}

		int i2s_wr_len = k;

		i2s_write(I2S_NUM_0, i2s_write_buff, i2s_wr_len, &bytes_written, portMAX_DELAY);
		offset += play_len; //累计播放数量自加
#if debug_voice_data
		printf("i2s_wr_len : %d j:  %d\n", i2s_wr_len, j);
		printf("======\n");
		for (int i = 0; i < 48; i += 2)
		{
			printf("%04x ", ((i2s_write_buff[i + 1] << 8) + i2s_write_buff[i]));
			if ((i + 1) % 15 == 0)
			{
				printf("\n");
			}
		}
		printf("======\n");
#endif
	}

	free(voice);
	free(resample_buff);
	free(i2s_write_buff);
	gpio_set_level(21, 0);
	ESP_LOGI(TAG, "stop pa mute,free spi cache,free music cache");
}

void play_task(void *arg)
{
	int play_list = -1;
	int tot_size = 0;
	//	SPI_2_TASK_T SPI_PLAY;
	audio_board_handle_t board_handle = audio_board_init();

	audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START);

	ESP_LOGI(TAG, "[2.2] Create i2s stream to write data to codec chip");
	i2s_stream_cfg_t i2s_writer = I2S_STREAM_CFG_DEFAULT();
	i2s_writer.type = AUDIO_STREAM_WRITER;
	i2s_writer.i2s_config.sample_rate = 48000;
	i2s_stream_init(&i2s_writer);

	vTaskDelay(pdMS_TO_TICKS(1000));

	audio_hal_set_volume(board_handle->audio_hal, vol);

	tot_size = sizeof(qdcg_data);
	play_voice(qdcg_data, tot_size);
	xSemaphoreGive(play_finish);
	uart_write_bytes(EX_UART_NUM, "ESP32 FINISH\r\n", 14);
	gpio_set_level(22, 0);
	while (1)
	{
		xQueueReceive(play_voice_task, &(play_list), (portTickType)portMAX_DELAY);
		if (play_list >= 0)
		{
			printf("reciver play list: %d\n", play_list);
			switch (play_list)
			{
			case nihao:
				tot_size = sizeof(nihao_data);
				play_voice(nihao_data, tot_size);
				xSemaphoreGive(play_finish);
				break;
			case zai:
				tot_size = sizeof(zai_data);
				play_voice(zai_data, tot_size);
				xSemaphoreGive(play_finish);
				break;
			case zsh:
				tot_size = sizeof(zsh_data);
				play_voice(zsh_data, tot_size);
				xSemaphoreGive(play_finish);
				break;
			case haode:
				tot_size = sizeof(haode_data);
				play_voice(haode_data, tot_size);
				break;
			case zxcg:
				tot_size = sizeof(zxcg_data);
				play_voice(zxcg_data, tot_size);
				break;
			case zxsb:
				tot_size = sizeof(zxsb_data);
				play_voice(zxsb_data, tot_size);
				break;
			case zxsbqjc:
				tot_size = sizeof(zxsbqjc_data);
				play_voice(zxsbqjc_data, tot_size);
				break;
			case wmtd:
				tot_size = sizeof(wmtd_data);
				play_voice(wmtd_data, tot_size);
				break;
			case wmtqc:
				tot_size = sizeof(wmtqc_data);
				play_voice(wmtqc_data, tot_size);
				break;
			case mygsb:
				tot_size = sizeof(mygsb_data);
				play_voice(mygsb_data, tot_size);
				break;
			default:
				printf("unknow playlist: %d\n", play_list);
				break;
			}
			play_list = -1;
		}
		//    	xQueuePeek(spi_2_task, &(SPI_PLAY), pdMS_TO_TICKS(20));
		//    	if(SPI_PLAY.rec_task == 1)
		//    	{
		//    		xQueueReceive(spi_2_task, &(SPI_PLAY), 1);
		//    		play_spi_voice(SPI_PLAY.buf,SPI_PLAY.rec_size);
		//    		SPI_PLAY.rec_task = 0;
		//    	}
	}
}
